package com.coderly.onlinegallerysharingplatform.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.coderly.onlinegallerysharingplatform.common.convention.errorcode.ErrorCode;
import com.coderly.onlinegallerysharingplatform.common.convention.exception.BizException;
import com.coderly.onlinegallerysharingplatform.common.response.Response;
import com.coderly.onlinegallerysharingplatform.model.dao.entity.FansDO;
import com.coderly.onlinegallerysharingplatform.model.dao.entity.FollowingDO;
import com.coderly.onlinegallerysharingplatform.model.dao.entity.UserDO;
import com.coderly.onlinegallerysharingplatform.model.dao.mapper.FansMapper;
import com.coderly.onlinegallerysharingplatform.model.dao.mapper.FollowingMapper;
import com.coderly.onlinegallerysharingplatform.model.dao.mapper.UserMapper;
import com.coderly.onlinegallerysharingplatform.model.dto.req.follow.*;
import com.coderly.onlinegallerysharingplatform.model.dto.resp.follow.FindFansListRespDTO;
import com.coderly.onlinegallerysharingplatform.model.dto.resp.follow.FindFollowingListRespDTO;
import com.coderly.onlinegallerysharingplatform.service.RelationService;
import com.coderly.onlinegallerysharingplatform.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
@RequiredArgsConstructor
public class RelationServiceImpl implements RelationService {

    private final UserService userService;
    private final FollowingMapper followingMapper;
    private final FansMapper fansMapper;
    private final UserMapper userMapper;

    /**
     * 关注用户
     *
     * @param followUserReqDTO
     * @return
     */
    @Override
    @Transactional
    public Response<?> follow(FollowUserReqDTO followUserReqDTO) {
        // 获取被关注用户的id
        Long followUserId = followUserReqDTO.getUserId();
        // 获取登录用户的id
        Long loginUserId = StpUtil.getLoginIdAsLong();
        // 校验：无法关注自己
        if (Objects.equals(followUserId, loginUserId)) {
            throw new BizException(ErrorCode.CANT_FOLLOW_YOUR_SELF);
        }
        // 校验被关注用户是否存在
        LambdaQueryWrapper<UserDO> eq = Wrappers.lambdaQuery(UserDO.class)
                .eq(UserDO::getId, followUserId);
        UserDO followedUser = userService.getOne(eq);
        if (Objects.isNull(followedUser)) {
            throw new BizException(ErrorCode.FOLLOW_USER_NOT_EXISTED);
        }
        // TODO 检验关注是否达到上限
        // TODO 校验是否已经关注该用户
        // 入库，完成关注逻辑
        // 关注成功，需要往数据库中添加两条记录
        // 关注表：
        Date now = new Date();
        int count = followingMapper.insert(FollowingDO.builder()
                .userId(loginUserId)
                .followingUserId(followUserId)
                .createTime(now)
                .build());
        if (count < 0) {
            throw new BizException(ErrorCode.OPERATION_ERROR);
        }
        count = fansMapper.insert(FansDO.builder()
                .userId(followUserId)
                .fansUserId(loginUserId)
                .createTime(now)
                .build());
        if (count < 0) {
            throw new BizException(ErrorCode.OPERATION_ERROR);
        }
        return Response.success(true);
    }

    @Override
    public Response<Page<FindFollowingListRespDTO>> findFollowingList(FindFollowingListReqDTO findFollowingListReqDTO) {
        // 获取分页参数
        int current = Math.max(findFollowingListReqDTO.getCurrent(), 1); // 确保页码最小为1
        int pageSize = Math.min(Math.max(findFollowingListReqDTO.getPageSize(), 1), 100); // 确保每页大小在1-100之间

        // 创建分页对象
        Page<FollowingDO> page = new Page<>(current, pageSize);

        // 构建查询条件
        LambdaQueryWrapper<FollowingDO> queryWrapper = Wrappers.lambdaQuery(FollowingDO.class)
                .eq(FollowingDO::getUserId, findFollowingListReqDTO.getUserId())
                .orderByDesc(FollowingDO::getCreateTime); // 按关注时间倒序排序

        // 执行分页查询
        Page<FollowingDO> followingPage = followingMapper.selectPage(page, queryWrapper);

        // 转换结果
        Page<FindFollowingListRespDTO> resultPage = new Page<>();
        BeanUtil.copyProperties(followingPage, resultPage, "records"); // 复制分页信息，但不复制记录

        // 处理记录列表
        List<FindFollowingListRespDTO> resultList = new ArrayList<>();
        for (FollowingDO followingDO : followingPage.getRecords()) {
            // 查询被关注用户的信息
            UserDO userDO = userMapper.selectById(followingDO.getFollowingUserId());
            if (userDO != null) {
                FindFollowingListRespDTO respDTO = new FindFollowingListRespDTO();
                BeanUtil.copyProperties(userDO, respDTO);
                respDTO.setUserId(userDO.getId());
                resultList.add(respDTO);
            }
        }
        // 设置结果列表
        resultPage.setRecords(resultList);

        log.info("查询用户{}的关注列表成功，当前页：{}，每页大小：{}，总记录数：{}",
                findFollowingListReqDTO.getUserId(), current, pageSize, resultPage.getTotal());
        return Response.success(resultPage);
    }

    @Override
    public Response<Page<FindFansListRespDTO>> findFansList(FindFansListReqDTO findFansListReqDTO) {
        // 获取分页参数
        int current = Math.max(findFansListReqDTO.getCurrent(), 1); // 确保页码最小为1
        int pageSize = Math.min(Math.max(findFansListReqDTO.getPageSize(), 1), 100); // 确保每页大小在1-100之间

        // 创建分页对象
        Page<FansDO> page = new Page<>(current, pageSize);

        // 构建查询条件
        LambdaQueryWrapper<FansDO> queryWrapper = Wrappers.lambdaQuery(FansDO.class)
                .eq(FansDO::getUserId, findFansListReqDTO.getUserId())
                .orderByDesc(FansDO::getCreateTime); // 按关注时间倒序排序

        // 执行分页查询
        Page<FansDO> fansPage = fansMapper.selectPage(page, queryWrapper);

        // 转换结果
        Page<FindFansListRespDTO> resultPage = new Page<>();
        BeanUtil.copyProperties(fansPage, resultPage, "records"); // 复制分页信息，但不复制记录

        // 处理记录列表
        List<FindFansListRespDTO> resultList = new ArrayList<>();
        for (FansDO fansDO : fansPage.getRecords()) {
            // 查询粉丝用户的信息
            UserDO userDO = userMapper.selectById(fansDO.getFansUserId());
            if (userDO != null) {
                FindFansListRespDTO respDTO = new FindFansListRespDTO();
                BeanUtil.copyProperties(userDO, respDTO);
                respDTO.setUserId(userDO.getId());
                resultList.add(respDTO);
            }
        }
        // 设置结果列表
        resultPage.setRecords(resultList);

        log.info("查询用户{}的关注列表成功，当前页：{}，每页大小：{}，总记录数：{}",
                findFansListReqDTO.getUserId(), current, pageSize, resultPage.getTotal());
        return Response.success(resultPage);
    }

    @Override
    @Transactional
    public Response<?> unFollow(UnFollowUserReqDTO unFollowUserReqDTO) {
        // 获取被取关用户的id
        Long unFollowUserId = unFollowUserReqDTO.getUserId();
        // 获取登录用户的id
        Long loginUserId = StpUtil.getLoginIdAsLong();
        
        // 校验：不能取关自己
        if (Objects.equals(unFollowUserId, loginUserId)) {
            throw new BizException(ErrorCode.CANT_UNFOLLOW_YOUR_SELF);
        }
        
        // 校验被取关用户是否存在
        LambdaQueryWrapper<UserDO> userQuery = Wrappers.lambdaQuery(UserDO.class)
                .eq(UserDO::getId, unFollowUserId);
        UserDO unfollowedUser = userService.getOne(userQuery);
        if (Objects.isNull(unfollowedUser)) {
            throw new BizException(ErrorCode.UNFOLLOW_USER_NOT_EXISTED);
        }
        
        // 校验是否已经关注该用户
        LambdaQueryWrapper<FollowingDO> followingQuery = Wrappers.lambdaQuery(FollowingDO.class)
                .eq(FollowingDO::getUserId, loginUserId)
                .eq(FollowingDO::getFollowingUserId, unFollowUserId);
        FollowingDO following = followingMapper.selectOne(followingQuery);
        if (Objects.isNull(following)) {
            throw new BizException(ErrorCode.NOT_FOLLOW_YET);
        }
        
        // 删除关注记录
        int count = followingMapper.delete(followingQuery);
        if (count <= 0) {
            throw new BizException(ErrorCode.OPERATION_ERROR);
        }
        
        // 删除粉丝记录
        LambdaQueryWrapper<FansDO> fansQuery = Wrappers.lambdaQuery(FansDO.class)
                .eq(FansDO::getUserId, unFollowUserId)
                .eq(FansDO::getFansUserId, loginUserId);
        count = fansMapper.delete(fansQuery);
        if (count <= 0) {
            throw new BizException(ErrorCode.OPERATION_ERROR);
        }
        
        log.info("用户{}取关用户{}成功", loginUserId, unFollowUserId);
        return Response.success(true);
    }

    /**
     * 检查登录用户是否已经关注该用户
     * @param checkLoginUserIsFansReqDTO 关注用户
     * @return
     */
    @Override
    public Response<?> checkLoginUserIsFans(CheckLoginUserIsFansReqDTO checkLoginUserIsFansReqDTO) {
        // 被关注的用户
        Long followedReqDTOUserId = checkLoginUserIsFansReqDTO.getUserId();
        // 当前登录用户
        Long loginUserId = StpUtil.getLoginIdAsLong();
        LambdaQueryWrapper<FollowingDO> eq = Wrappers.lambdaQuery(FollowingDO.class)
                .eq(FollowingDO::getUserId, loginUserId)
                .eq(FollowingDO::getFollowingUserId, followedReqDTOUserId);
        FollowingDO followingDO = followingMapper.selectOne(eq);
        if (Objects.isNull(followingDO)) {
            // 这里不要抛异常
            return Response.success(false);
        }
        return Response.success(true);
    }
}


